﻿using AdminModels;
using CoinModels;
using CoinModels.Cryptsy;
using Common;
using Entities;
using Entities.CoinEntities.Cryptsy;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace DataPool.Tickers
{
    public static class CryptsyDataCollector
    {
        private static int maxAttempts = Settings.GetSetting("MaxTickerCollectAttempts", 5);
        private static string baseApiAddress = @"http://pubapi.cryptsy.com/";
        private static string methodCall = @"api.php?method=";
        private static string callType = @"marketdatav2";

        /// <summary>
        /// Pools Data from a response message, or logs an error if
        /// it can't
        /// </summary>
        /// <param name="attempt">Number of Times Attempted, default = 0</param>
        /// <returns>If Data was Pooled</returns>
        public static List<CryptsyCoin> CollectData(int attempt = 0)
        {
            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri(baseApiAddress);
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            HttpResponseMessage response = client.GetAsync(methodCall + callType).Result;
            List<CryptsyCoin> markets = new List<CryptsyCoin>();
            DateTime addTime = DateTime.Now;

            if (attempt < maxAttempts)
            {
                try
                {
                    if (response.IsSuccessStatusCode)
                    {
                        // Get the serialized JSON
                        string rawData = response.Content.ReadAsStringAsync().Result;
                        if (string.IsNullOrWhiteSpace(rawData))
                        {
                            throw new Exception("Empty Response from Cryptsy");
                        }

                        // Deserialize the JSON
                        JsonSerializerSettings settings = DefaultValues.GetJsonSettings();
                        CryptsyWrapper cryptsyJSON;
                        try
                        {
                            cryptsyJSON = JsonConvert.DeserializeObject<CryptsyWrapper>(rawData, settings);
                        }
                        catch (Exception ex)
                        {
                            throw new Exception("Improper Serialization from Cryptsy", ex);
                        }

                        // Break the wrappers and reserialize (so it can be looped)
                        var rawMarkets = JsonConvert.DeserializeObject<Dictionary<string, object>>(JsonConvert.SerializeObject(cryptsyJSON.returnObject.markets), settings);
                        foreach (var rawMarket in rawMarkets)
                        {
                            var jRawMarket = (JObject)rawMarket.Value;
                            var market = JsonConvert.DeserializeObject<CryptsyCoin>(JsonConvert.SerializeObject(jRawMarket), settings);
                            market.updatedat = addTime;
                            markets.Add(market);
                        }

                        // Persist Data, if fail try again (unit you hit max number of attempts)
                        CryptsyCoin.PersistCoinCollection(markets);
                    }
                    else
                    {
                        throw new Exception("Failed Response From Cryptsy: " + response.ReasonPhrase);
                    }
                }
                catch (Exception ex)
                {
                    ErrorLog.SaveLog(ex, "CryptsyTickerDataPooler", ErrorType.MarketGrab);
                    markets = CollectData(++attempt);
                }
            }
            else
            {
                ErrorLog.SaveLog(new Exception("Cryptsy Data Grab Fail: " + attempt + " failed attempts.")
                    , "CryptsyDataPooler", ErrorType.Summary);
            }

            return markets;
        }

        /// <summary>
        /// Gets list of most recently collected Coins
        /// </summary>
        /// <returns>List of most recently collected coins</returns>
        public static List<CryptsyCoin> GetMostRecentCryptsyCoins()
        {
            List<CryptsyCoin> coins = new List<CryptsyCoin>();
            CryptsyCoinEntity[] tempList;

            using (AegirContext db = new AegirContext())
            {
                DateTime mostRecentDate = db.Cryptsy_Coin.Max(x => x.updatedat);
                ErrorLog.SaveLog(new Exception("DateTime Cryptsy " + mostRecentDate));
                tempList = db.Cryptsy_Coin.Where(x => x.updatedat == mostRecentDate).ToArray();
            }

            foreach (var entity in tempList)
            {
                coins.Add(CryptsyCoin.ConvertToModel(entity));
            }

            return coins;
        }
    }
}